package cn.tnar.yunpark.service.impl;

import cn.tnar.yunpark.model.*;
import cn.tnar.yunpark.service.BayService;
import cn.tnar.yunpark.service.ParkSpaceService;
import cn.tnar.yunpark.service.SensorEventDispatcher;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.amqp.core.AmqpTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

/**
 * Created by tieh on 2017/6/14.
 */
@Service
public class TnarSensorEventDispatcher implements SensorEventDispatcher {

    private static final Logger log = LoggerFactory.getLogger(TnarSensorEventDispatcher.class);

    @Autowired
    private BayService bayService;

    @Autowired
    private ParkSpaceService parkSpaceService;

    @Autowired
    private AmqpTemplate amqpTemplate;

    @Value("${tnar.kesb.supportSensorStatus}")
    private boolean supportSensorStatus = false;

    @Value("${tnar.notifyPda}")
    private boolean notifyPda = false;

    private ExecutorService scheduler = Executors.newFixedThreadPool(5);

    @Override
    public void dispatch(KesbStatus event) {
        scheduler.submit(new NotifyLbmTask(event));
        if(event instanceof SpaceStatus) {
            if(notifyPda) {
                scheduler.submit(new NotifyPdaTask((SpaceStatus) event));
            }
        }
    }

    private class NotifyLbmTask implements Runnable {

        private KesbStatus status;

        public NotifyLbmTask(KesbStatus status) {
            this.status = status;
        }

        @Override
        public void run() {
            try {
                if(status instanceof SpaceSensorStatus && !supportSensorStatus) {
                    // KESB 不支持 Sensor Status 时不发送
                    return;
                }
                log.info("=> KESB " + status);
                bayService.BatchSyncBayStatus(StatusToKesb.INSTANCE.apply(status));
            } catch (Exception e) {
                log.warn("Space sensor status to LBM error: " + e.getMessage());
            }
        }
    }

    /**
     * 通过MQ通知PDA车位状态变化
     */
    private class NotifyPdaTask implements Runnable {

        private SpaceStatus event;

        public NotifyPdaTask(SpaceStatus event) {
            this.event = event;
        }

        @Override
        public void run() {
            try {
                ParkSpace spaceInfo = parkSpaceService.getSpaceInfoBySensorId(event.getSensorId());
                if (spaceInfo == null) {
                    log.warn("Park space not found for sensor id " + event.getSensorId());
                    return;
                }

                String regionShortCode = spaceInfo.getRegionCode().substring(spaceInfo.getParkCode().length());
                String topic = "space." + spaceInfo.getParkCode() + "." + regionShortCode;
                ParkSpaceStatus spaceEvent = new ParkSpaceStatus(spaceInfo, event);

                log.info("=> MQ " + topic + ": " + spaceEvent.toString());
                amqpTemplate.convertAndSend("amq.topic", topic, spaceEvent);
            } catch (Exception e) {
                log.warn("Notify space status error", e);
            }
        }
    }
}
